import {
	AppCodeListHelperBase,
	IAppCodeListHelper,
	ICodeList,
	ICodeListItem,
	ICodeListResult,
	IContext,
	IHttpResponse,
	IParam,
} from '@/core';

export class AppCodeListHelper
	extends AppCodeListHelperBase
	implements IAppCodeListHelper
{
	/**
	 * 单例服务
	 *
	 * @protected
	 * @static
	 * @type {IAppCodeListHelper}
	 * @memberof AppCodeListHelper
	 */
	private static service: IAppCodeListHelper;

	/**
	 * 获取实例
	 *
	 * @static
	 * @return {*}  {IAppCodeListHelper}
	 * @memberof AppCodeListHelper
	 */
	static getInstance(): IAppCodeListHelper {
		if (!this.service) {
			this.service = new AppCodeListHelper();
		}
		return this.service;
	}

	/**
	 * 动态代码表缓存(加载中)
	 *
	 * @type {Map<string,any>}
	 * @memberof AppCodeListHelper
	 */
	private static codeListCache: Map<string, any> = new Map();

	/**
	 * 动态代码表缓存(已完成)
	 *
	 * @type {Map<string,any>}
	 * @memberof AppCodeListHelper
	 */
	private static codeListCached: Map<
		string,
		{ result: ICodeListResult; expirationTime?: number }
	> = new Map();

	/**
	 * 获取代码表数据（包含动态/静态/预定义统一入口）
	 * @param tag 代码表标识
	 * @param context 应用上下文
	 * @param viewParams 视图参数
	 */
	getCodeListItems(
		tag: string,
		context?: IContext,
		viewParams?: IParam
	): Promise<ICodeListResult> {
		//  根据tag 获取代码表标识
		const codeList = App.getAppCodeListConfig()[tag];
		if (!codeList) return Promise.resolve(this.handleCodeListData([], false));
		// 根据代码表类型
		if (Object.is(codeList.codeListType, 'STATIC')) {
			return this.getItemsWithStatic(codeList, context, viewParams);
		} else {
			if (codeList.predefinedType) {
				return this.getItemsWithPredefined(codeList, context, viewParams);
			} else {
				return this.getItemsWithDynamic(codeList, context, viewParams);
			}
		}
	}

	/**
	 * 获取静态代码表数据
	 * @param tag 代码表标识
	 * @param context 应用上下文
	 * @param viewParams 视图参数
	 */
	getItemsWithStatic(
		codeList: ICodeList,
		context?: IContext,
		viewParams?: IParam
	): Promise<ICodeListResult> {
		const { items } = codeList;
		if (!codeList || !items) {
			return Promise.resolve(this.handleCodeListData([], false));
		}
		return Promise.resolve(this.handleCodeListData(items));
	}

	/**
	 * 获取动态代码表数据
	 * @param tag 代码表标识
	 * @param context 应用上下文
	 * @param viewParams 视图参数
	 */
	getItemsWithDynamic(
		codeList: ICodeList,
		context?: IContext,
		viewParams?: IParam
	): Promise<ICodeListResult> {
		return new Promise((resolve: any) => {
			const { isEnableCache, cacheTimeout } = codeList;
			// 启用缓存
			if (isEnableCache) {
				const tag: string = codeList.codeName;
				// 加载完成执行回调
				const callback = (tag: string, promise: Promise<ICodeListResult>) => {
					promise.then((result: ICodeListResult) => {
						const { data } = result;
						if (data.length > 0) {
							AppCodeListHelper.codeListCached.set(tag, {
								result,
								expirationTime:
									cacheTimeout === -1
										? -1
										: new Date().getTime() + cacheTimeout,
							});
							AppCodeListHelper.codeListCache.delete(tag);
							resolve(result);
						} else {
							resolve(this.handleCodeListData([], false));
						}
					});
				};
				// 先从已缓存完成的代码表Map中获取
				const activeCodeList = AppCodeListHelper.codeListCached.get(tag);
				if (activeCodeList?.expirationTime) {
					if (
						activeCodeList.expirationTime === -1 ||
						new Date().getTime() <= activeCodeList.expirationTime
					) {
						resolve(activeCodeList.result);
					}
				}
				// 加载中，UI又需要数据，解决连续加载同一代码表问题
				if (AppCodeListHelper.codeListCache.get(tag)) {
					callback(tag, AppCodeListHelper.codeListCache.get(tag));
				} else {
					const result = this.getCodeListData(codeList, context, viewParams);
					AppCodeListHelper.codeListCache.set(tag, result);
					callback(tag, result);
				}
			} else {
				resolve(this.getCodeListData(codeList, context, viewParams));
			}
		});
	}

	/**
	 * 获取预定义代码表数据
	 * @param tag 代码表标识
	 * @param context 应用上下文
	 * @param viewParams 视图参数
	 */
	getItemsWithPredefined(
		codeList: ICodeList,
		context?: IContext,
		viewParams?: IParam
	): Promise<ICodeListResult> {
		return new Promise((resolve: any) => {
			const { codeListTag, appDataEntity } = codeList;
			if (!appDataEntity) {
				return resolve({ ok: false, data: null });
			}
			const callback = (tag: string, promise: Promise<IHttpResponse>) => {
				promise
					.then((res: IHttpResponse) => {
						// 兼容两者，有的从items里取，有的直接拿
						const result: ICodeListResult = this.handleCodeListData(res.data);
						if (result.data.length > 0) {
							AppCodeListHelper.codeListCached.set(`${tag}`, {
								result: result,
							});
							return resolve(result);
						} else {
							return resolve([]);
						}
					})
					.catch((result: any) => {
						return resolve(result);
					});
			};
			// 加载中，UI又需要数据，解决连续加载同一代码表问题
			if (AppCodeListHelper.codeListCache.get(`${codeListTag}`)) {
				callback(
					codeListTag,
					AppCodeListHelper.codeListCache.get(`${codeListTag}`)
				);
			} else {
				App.getDataService(appDataEntity, context).then((dataService: any) => {
					if (!dataService) return resolve(this.handleCodeListData([], false));
					// 待测试 数据服务未实现getPredefinedCodeList;
					const result: Promise<IHttpResponse> =
						dataService.getPredefinedCodeList(codeListTag);
					AppCodeListHelper.codeListCache.set(`${codeListTag}`, result);
					callback(codeListTag, result);
				});
			}
		});
	}

	/**
	 * 获取代码表数据（动态代码表）
	 *
	 * @param {IParam} codeList 代码表对象
	 * @param {IContext} [context={}] 应用上下文
	 * @param {IParam} [viewParams={}] 视图参数
	 * @memberof AppCodeListHelper
	 */
	private async getCodeListData(
		codeList: IParam,
		context?: IContext,
		viewParams?: IParam
	): Promise<ICodeListResult> {
		try {
			const {
				appDataEntity,
				appDEDataSet,
				textPSAppDEField,
				valuePSAppDEField,
				pValuePSAppDEField,
			} = codeList;
			if (
				!appDataEntity ||
				!appDEDataSet ||
				!textPSAppDEField ||
				!valuePSAppDEField
			) {
				console.error('动态代码表获取数据异常[查询参数不足]');
			}
			const dataService = await App.getDataService(appDataEntity, context);
			const response: IHttpResponse = await dataService[appDEDataSet](
				context,
				viewParams,
				false
			);
			const { success, data } = response;
			if (success) {
				const items: IParam[] = [];
				if (data && data.length > 0) {
					data.forEach((element: IParam) => {
						items.push({
							value: element[valuePSAppDEField],
							text: element[textPSAppDEField],
							pvalue: element[pValuePSAppDEField],
						});
					});
				}
				return this.handleCodeListData(items);
			} else {
				console.error('动态代码表获取数据异常[网络请求异常]');
				return this.handleCodeListData([], false);
			}
		} catch (error: any) {
			console.error(`动态代码表获取数据异常[${JSON.stringify(error)}]`);
			return this.handleCodeListData([], false);
		}
	}

	/**
	 * 处理返回结果
	 *
	 * @private
	 * @param {IParam[]} items
	 * @param {boolean} [ok=true]
	 * @return {*}  {ICodeListResult}
	 * @memberof AppCodeListHelper
	 */
	private handleCodeListData(items: IParam[], ok = true): ICodeListResult {
		const data: ICodeListItem[] = [];
		items.forEach((item: IParam) => {
			data.push({
				color: item.color,
				text: item.text,
				value: item.value,
				pvalue: item.pvalue,
				codeName: item.codeName,
				textResTag: item.textResTag,
				icon: item.icon,
				textClass: item.textClass,
				data: item.data,
				disable: item.disable,
			});
		});
		return { ok: ok, data: data };
	}
}
